import { ModalsDemos } from '@docs/demos';
import { Layout } from '@/layout';
import { MDX_DATA } from '@/mdx';

export default Layout(MDX_DATA.Modals);

## Installation

<InstallScript packages="@mantine/modals" />

## Setup ModalsProvider

Wrap your app with `ModalsProvider` component:

```tsx
import { MantineProvider } from '@mantine/core';
import { ModalsProvider } from '@mantine/modals';

function Demo() {
  return (
    <MantineProvider>
      <ModalsProvider>{/* Your app here */}</ModalsProvider>
    </MantineProvider>
  );
}
```

## Confirm modal

@mantine/modals package includes special modal that can be used for confirmations.
Component includes confirm and cancel buttons and supports children to display additional
information about action. Use `openConfirmModal` function to open a confirm modal:

<Demo data={ModalsDemos.confirm} />

`openConfirmModal` function accepts one argument with following properties:

- `modalId` – modal id, defaults to random id, can be used to close modal programmatically
- `children` – additional modal content displayed before actions
- `onCancel` – called when cancel button is clicked
- `onConfirm` – called when confirm button is clicked
- `closeOnConfirm` – should modal be closed when confirm button is clicked, defaults to `true`
- `closeOnCancel` – should modal be closed when cancel button is clicked, defaults to `true`
- `cancelProps` – cancel button props
- `confirmProps` – confirm button props
- `groupProps` – buttons [Group](/core/group/) props
- `labels` – cancel and confirm buttons labels, can be defined on ModalsProvider

Using this properties you can customize confirm modal to match current context requirements:

<Demo data={ModalsDemos.confirmCustomize} />

To setup shared labels for confirm modals set `labels` on `ModalsProvider`:

```tsx
import { ModalsProvider } from '@mantine/modals';

function Demo() {
  return (
    <ModalsProvider labels={{ confirm: 'Submit', cancel: 'Cancel' }}>
      {/* Your app here */}
    </ModalsProvider>
  );
}
```

## Context modals

You can define any amount of modals in ModalsProvider context:

```tsx
import { Button, Text } from '@mantine/core';
import { ContextModalProps, ModalsProvider } from '@mantine/modals';

const TestModal = ({
  context,
  id,
  innerProps,
}: ContextModalProps<{ modalBody: string }>) => (
  <>
    <Text size="sm">{innerProps.modalBody}</Text>
    <Button fullWidth mt="md" onClick={() => context.closeModal(id)}>
      Close modal
    </Button>
  </>
);

function Demo() {
  return (
    <ModalsProvider
      modals={{ demonstration: TestModal /* ...other modals */ }}
    >
      {/* Your app here */}
    </ModalsProvider>
  );
}
```

And then open one of these modals with `modals.openContextModal` function.
`modals.openContextModal` function accepts 2 arguments: modal key (should match one defined on ModalsProvider) and modal props:

<Demo data={ModalsDemos.context} />

## Typesafe context modals

By default `innerProps` and `modal` are not typesafe. You can add typesafety with a Typescript module declaration.

```tsx
const TestModal = ({
  context,
  id,
  innerProps,
}: ContextModalProps<{ modalBody: string }>) => (
  <>
    <Text size="sm">{innerProps.modalBody}</Text>
    <Button fullWidth mt="md" onClick={() => context.closeModal(id)}>
      Close modal
    </Button>
  </>
);
const modals = {
  demonstration: TestModal,
  /* ...other modals */
};
declare module '@mantine/modals' {
  export interface MantineModalsOverride {
    modals: typeof modals;
  }
}
function Demo() {
  return (
    <ModalsProvider modals={modals}>
      {/* Your app here */}
    </ModalsProvider>
  );
}
```

Typesafe context modals will force you to use the correct types for `openContextModal`:

```tsx
import { closeModal, openContextModal } from '@mantine/modals';

openContextModal({
  modal: 'demonstration',
  title: 'Test modal from context',
  innerProps: {
    modalBody:
      'This modal was defined in ModalsProvider, you can open it anywhere in you app with useModals hook',
  },
});
closeModal('demonstration');
```

## Content modals

With `modals.open` function you can open a modal with any content:

<Demo data={ModalsDemos.content} />

## Multiple opened modals

You can open multiple layers of modals. Every opened modal is added as first element in modals queue.
To close all opened modals call `modals.closeAll()` function:

<Demo data={ModalsDemos.multipleSteps} />

## Modal props

You can pass props down to the [Modal](/core/modal) component by adding them to the
argument of every `modals.x` function. Example of setting `radius`, `size` and `withCloseButton`
props:

<Demo data={ModalsDemos.modalProps} />

## Dynamic Content and the modals manager

The Modals manager allows you to dynamically update the content and properties of both standard and context modals after they are opened.

To update regular modals, use the `modals.updateModal` function:

<Demo data={ModalsDemos.updateModal} />

Context modals can also be updated dynamically using `modals.updateContextModal`:

<Demo data={ModalsDemos.updateContextModal} />
